Webアプリを創る 😊クリエイティブWeb

カテゴリー: Web アプリ

.NET Core で PostgreSQL を使ってみたら結構いけていたという話

2016年12月15日

これは PostgreSQL Advent Calendar 2016の15日目の記事です。

この Web サイトは、今年の4月から ASP.NET を Core の方に更新して Ubuntu サーバーで運用しています。実際に運用してみて、IIS よりも Nginx を使う方が便利だと思うようになってきたので、サーバーはすべて Linux サーバーにする予定です。

その際の問題は、データベースをどうするかということです。ASP.NET とはなんといっても SQL Server を使うのが定番です。それで、自分も SQL Server Express を使ってアプリを作っていました。しかし、残念なことに SQL Server が Linux に対応するのは来年の半ばということです。

最近、PostGIS を使いたいという思惑もあって、PostgreSQL を使ってみたら、結構いけていると感じたので、この記事を書くことにしました。まだ、使い始めて1ヶ月なので、今後問題が見つかるかもしれないので最終的どうなるかはわかりませんが、PostgreSQL を使っていこうと思っています。

Entity Framework Core で使う

.NET Core や .NET Framework から、PostgreSQL を使う場合は、Npgsql というデータプロバイダーを使用します。Npgsql には、Entity Framework Core(EF Core)用のプロバイダーもあるので、EF Core で使っている範囲では、SQL Server を使うのと違いは殆どありません。

参考 Npgsql の EF Core 用のドキュメント

例として、Visual Studio の ASP.NET Core の Web アプリケーションのテンプレートで認証を「個別のユーザーアカウント」にした場合に、EF Core が使用されているので、それを PostgreSQL を使うように修正してみます。

  1. Nuget パッケージ の追加 Npgsql.EntityFrameworkCore.PostgreSQL を追加します。

  2. Startup.cs の修正 以下のように、options.UseSqlServer と SQL Server を使う設定になっているので、

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
    services.AddIdentity<ApplicationUser, IdentityRole>()
       .AddEntityFrameworkStores<ApplicationDbContext>()
       .AddDefaultTokenProviders();
    ------ 以下省略
}

options.UseNpgsql に変更して、Npgsql を使うようにします。

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddDbContext<ApplicationDbContext>(options =>
                options.UseNpgsql(Configuration.GetConnectionString("DefaultConnection")));
    services.AddIdentity<ApplicationUser, IdentityRole>()
       .AddEntityFrameworkStores<ApplicationDbContext>()
       .AddDefaultTokenProviders();
    ------ 以下省略
}
  1. appsettings.json に記載してある接続文字列を修正します。
{
  "ConnectionStrings": {
    "DefaultConnection": "Server=localhost;Database=test;Username=postgres;Password=password"
  },
------ 以下省略
}

SQL Server から PostgreSQL を使うように変更するのはそれだけです。

接続文字列に設定したユーザーが、データベースを作成できる権限を持っているユーザーであれば、これでデータベースも勝手に作ります。もし、そうでなければ事前にデータベースを作っておきます。

ただし、それで Run して、ユーザーの登録をしようとするとエラーになります。Data ディレクトリに Migration フォルダーが作成されていて、SQL Server 用のものが事前に作られているためです。 それで、それらのファイルを削除してからするとちゃんとしたエラーメッセーが出ます。メーセージの通りにマイグレーションをしてやると正常に動くようになります。

A database operation failed while processing the request.
NpgsqlException: Exception while reading from stream 
IOException: Unable to read data from the transport connection: 既存の接続はリモート ホストに強制的に切断されました。. 
SocketException: 既存の接続はリモート ホストに強制的に切断されました。 
Use migrations to create the database for ApplicationDbContext
In Visual Studio, use the Package Manager Console to scaffold a new migration and apply it to the database:
PM> Add-Migration [migration name] 
PM> Update-Database
Alternatively, you can scaffold a new migration and apply it from a command prompt at your project directory:
> dotnet ef migrations add [migration name] 
> dotnet ef database update

コードファーストで開発する場合は、SQL Server なのか PostgreSQL なのかを気にしなくても開発できると思います。

細かい点でいうと作成されたテーブルをみると下の図のようにカラム名が Pascal ケースになっています。

AdWordのアカウントのリンクの画像

SQL Server では、カラム名の大文字小文字を区別しないのでPascalケースは便利なのですが、PostgreSQL では、列名の大文字小文字を区別し、SQL文の中の列名は小文字に変換されます。それで、カラム名が「AspNetUsers」だと SQL 文の中では、常に二重引用符でくくって "AspNetUsers" としないといけなくなって結構手間になります。そのまま Pascal ケースで使うのか、それとも fluent API か attributes を使ってスネークケースに変換して使うのか悩ましいところです。自分は EF Core で使うのが主で、生の SQL をあまり使わないので、Pascal ケースのままでもいいのではないかと思っています。

データベースファーストの場合も、SQL Server を使うのと殆ど違いはなく、Microsoft.EntityFrameworkCore.SqlServer.Design の代わりに Npgsql.EntityFrameworkCore.PostgreSQL.Design を追加し、

dotnet cli の場合は、

dotnet ef dbcontext scaffold "Host=localhost;Database=mydatabase;Username=myuser;Password=mypassword" Npgsql.EntityFrameworkCore.PostgreSQL

Powershell の場合は、

Scaffold-DbContext "Host=localhost;Database=mydatabase;Username=myuser;Password=mypassword" Npgsql.EntityFrameworkCore.PostgreSQL

というように、Microsoft.EntityFrameworkCore.SqlServerNpgsql.EntityFrameworkCore.PostgreSQL に置き換えてやれば、EF model を作成できます。

なお、DbContext のプロパティ名はカラム名を Pascal ケースに変換したものになります。

以上のように EF Core で使う限りにおいては、SQL Server を使うのと差はなく、実際に使っても今のところ大きな問題はでていません。

PostgreSQL を使うメリット、デメリット

SQL Server よりも便利な点としては、where 句で下のように正規表現を使うとサーバー側で処理をしてくれるという点です。( 参照 ドキュメント)

var customersStartingWithA = context.Customers.Where(c => Regex.IsMatch(c.CompanyName, "^A"));

まだ使っていませんが、circle 等の幾何データ型、配列型、JSONB型のマッピングは可能なようなので、EF Core でも、これらのデータの取得と更新は可能なようです。

ただし、PostgreSQL の独自の機能を本格的に使うためには、EF Core ではなくて、Npgsql を直接使う必要があり少し手間がかかります。

でも、少し調べてみると、.NET で PostgreSQL を Document Db として使うためのソフトとして Marten というソフトが開発されています。まだ使い始めたばかりですが、結構使いやすい感じです。

PostgreSQL のデメリットといえば、慣れの問題かも分かりませんが pgAdmin よりは、Visual Studio Management Studio の方が使いやすいという点です。

PostgreSQL にするか MySQL にするか

Linux で動作するオープンソースの RDB といえば、PostgreSQL よりも MySQL の方が有名です。

まず、.NET Core 対応という点で比較すると、PostgreSQL の方は、Npgsql の .NET Core 対応はアルファ版が出てもう1年以上になります。その後も開発が進められてきており、かなり安定してきていると思います。一方、MySQL の方は .NET Core に Connector/Net 7 で対応予定で現在開発版が公開されています。

最近の状況では、ZDNet Japan の「PostgreSQL」がスタートアップ企業に選ばれる理由という記事が参考になると思います。以下に最近のデータを載せておきます。

Hacker News Hiring Trends 2016年11月 Hacker News Hiring Trendsの画像

indeed Job Trends indeed Job Trendsのリンクの画像

ASP.NET Core を格安 VPS で使う

2016年10月1日

この Web サイトを Ubuntu サーバーで運用を始めて6ヶ月になりました。その間に特に問題はありませんでした。むしろ、Linux サーバーに慣れてきて、テキストベースの設定が結構便利だと思うようになりました。

それで、格安 VPS を使って、ASP.NET Core アプリを動かしてみました。使ったのは、「さくらの VPS」1G 月額972円で、Webサイトは pp22.net です。サイトの中身は、まだ、このサイトのコピーです。

さくらの VPS の設定及び ASP.NET Core アプリを Linux で公開する手順については以下のページにメモをしています。

pp22.net の Web サイトが動作し始めたので、WebPagetest を使ってスピードテストをしてみました。結果は殆ど差がなく、格安 VPS でも、Web アプリの作り方次第では十分使えることが分かりました。

creativeweb.jp creativeweb.jpのスピードテストの結果の図

pp22.net creativeweb.jpのスピードテストの結果の図

なお、pp22.net の方がロード時間が短いのは、下部に Google アドセンスの「関連コンテンツ ユニット」が付いていないことが影響していると思います。

格安 VPS を実際に使ってみて、ASP.NET Core を使う上での課題は、データベースをどうするかということです。このサイトは、ファイルベースなので問題なくインストールできたのですが、通常の Web アプリではデータベースが必須になる場合が多いと思います。

ASP.NET Core と親和性が高いのは SQL Sever Express ですが、Linux 版が出るのは来年の中頃です。Linux サーバー以外に Windows サーバーを立てて、そこに SQL Sever Express をインストールすれば動作に問題はないのですが、格安 VPS を使うという趣旨ではどうかと思います。

Linux で一番使われている RDB である MySQL の場合は、公式ドライバー MySQL Connector/NET がまだ開発中で安定性に問題があります。

そういうことで、現時点で格安にしようとすれば PostgreSQL ということになると思って現在テスト中です。PostgreSQL は、.NET Core への対応を積極的に行ってきたこと、また、JSONサポートも積極的に進めているのでスタートアップ向けにはいいのではないかと思っています。

RDB でなくててもいいのであれば、次のようなドライバーが .NET Core に対応しています。ただし、ServiceStack.Redis の方は、.NET Core 対応についてはアルファ版です。

また、クラウドのストレージを利用する場合は、次のようなツールが .NET Core に対応しているので、主なものは使えるようになっています。

ドメイン名を変更して、「マンガでなれる?WEBデザイナー講座」を始めました

2015年6月22日

ドメイン名を awoni.net から creativeweb.jp に変更しました。変更した大きな理由はなく、今後も web 関係のことを書いていくのだったら web が入っているドメイン名にした方がわかりやすいのではないかと思っただけです。最近は、このサイトの更新があまりできていないので、これを機会にもう少し更新の頻度をあげていきたいと思っています。

また、「マンガでなれる?WEBデザイナー講座」を始めました。最近、PCの他にスマートフォン、タブレット等色々なデバイスが増えて、Web デザインの方法が大きく変わってきたので、自分でも勉強しようと思っていたところ、フリーWEBデザイナーのミカ(栗本美香)さんが、マンガが得意なのを思い出して依頼したものです。

自分は、作りたいものがあるから Webアプリを作るというタイプで、基本的に一人で Web アプリを作っています。一人で全部していると、きれいなプログラムを書くことも優れたデザインのサイトを作ることも無理ですが、少しでもいいものは作りたいと思っています。

一人で作ることのメリットは効率がいいことで、今回のマンガも2週間ほどで公開できました。やり残してることも多いのですが、運用しながら修正していけるというのも Web のいいところだと思っています。

マンガでなれる?WEBデザイナー講座の図

 

5374 徳島市版を作成してみました

2015年5月17日

Windows 10 Insider Preview と Visual Studio 2015 RC のテストを兼ねて、Code for Kanazawa が作った「いつ、どのゴミが収集されているのか」をわかるWebアプリ 5374.jp の徳島市版を作ってみました。

Windows 10 も VS 2015 も自分の使った限りでは、エラーが発生することなく使えています。今年の夏に発売予定ですが、準備の方は順調に進んでいるようです。VS 2015 で、ASP.NET 5 については、あまり使っていませんが、ASP.NET 4.6 では製品版といってもいい状況で、実際の運用環境で使ってもいいという "Go-Live" ライセンスになっているというのもうなづけます。

5374.jp については、徳島市の場合は隔週及び4週毎のごみの収集があるのに、それに対応していないため、カスタマイズをしてみました。詳しくは、GitHub の方に記載しています。

徳島市版を作成した理由の一つには、JavaScript をどこまで使うのがいいのかということに対するテストという意味合いもあります。結局は、JavaScriptにどれぐらい慣れているのかということが一番大きな要素になると思いますが、自分の場合はロジックについてはC#で書いた方が楽です。JavaScript は一般的には手軽なのですが、Date を使うのは結構ややこしいです。自分の場合は、メンテナンスまで考えると今までどおり JavaScript は、UI 部分だけで使った方がいいと思いました。

5374.jp の場合、収集日を通知してくれる機能が欲しいと思うので、Cordova で作るのがいいのか、Xamarin で作るのがいいのか試してみたいと思っています。1月にアプリを作りかけたときは、表示の項目数が多かったので、Xamarin.Forms ではレイアウトの処理に時間が掛かりすぎました。5374.jp の場合は、それと比較するとかなり簡素なので Xamarin.Forms でも余り問題がないと思うので、比較するのには丁度いいと思っています。

Bootstrap を使ってレスポンシブ Web でモバイル対応しています

2015年2月14日

最近は、「統計メモ帳」のサイトのモバイル対応をしています。当初は、ユーザー エージェントによる振り分けで対応しようと思っていたのですが、作業中にレスポンシブ Web でもできるのではないかと言うことに気づいて、テストしたら問題がないようなので、Bootstrap を使って、レスポンシブ Web でモバイル対応を進めています。

image

統計メモ帳だけで、テンプレートが60ページあるので、もし振り分けにしていたら、テンプレートが120ページになったということで、後の管理を考えると、できるだけレスポンシブ Web で対応した方がいいと思っています。

自分が管理で一番大変だと思っているのは、テンプレートの修正や CSS の管理です。今回もまだ50ページ以上のテンプレートの修正作業が残っていて、かなり大変な作業です。プログラムの部分は、Visual Studio が結構優秀なのと、ソースは Git に入れてあるので意外とスムーズにいっています。

CSS には、デザイン能力も必要ないし、変数も関数もないのでプログラムの能力も必要ないしで、3ヶ月も勉強すれば誰でもできると思われていて、webコーダーは最底辺の職種になっています。そのためかどうかは分かりませんが、CSS の管理はあまり考えられていなかったと思います。しかし、CSS には、名前空間がないので、そのクラスがどこで使われているかを調べるのに手間がかかります。だから本当は命名規則をきちんとしておくことが非常に重要です。

Bootstrap を実際に使ってみて感じたことは、普段に使うコンポーネントを一通り作ってくれて、そのコンポーネントに名前をつけてくれたということが偉大だと思います。CSS のクラスの名前にデファクトスタンダードを作ったということは大いに評価すべきで、以後の管理は少しは楽になると思います。

Bootstrapは、所詮はコンポーネントの集まりで、利用する人の能力によってどうにでもなります。Bootstrap は、カスタマイズをするのが難しく Bootstrap 臭がするからダメだという人は、CSS をカスタマイズする能力がない人です。自分のようにデザイン能力がない人間が使えばしょぼいデザインのものしかできません。

レスポンシブ Web では、以前は Google アドセンスを入れるのが難しかったのですが、レスポンシブ広告ユニットが使用できるようになっているので、それほど問題なく導入することができました。